<!-- eslint-disable no-undef -->
<script setup>
import { ref, watch, onMounted, onUnmounted } from 'vue'
import ActionMenu from './component/ActionMenu.vue'
import LoadGame from './component/LoadGame.vue'
import { useWindowSize, useThrottleFn } from '@vueuse/core'
import { getQueryParams } from '@/utils/tools'
import { storeToRefs } from 'pinia'
import useMenuStore from '@/pinia/menuStore'
import useUserStore from '@/pinia/userInfo'
import { useMouse } from '@/hooks/mouse.js'
import { useBroad } from '@/hooks/broad.js'

const remoteId = '4444'
const menuStore = useMenuStore()
const userStore = useUserStore()
const { isMouseLock, screenType, isStream } = storeToRefs(menuStore)
const { userInfo } = storeToRefs(userStore)
const videoStream = ref(null)
const videoBox = ref(null)
const cursorRef = ref(null)
const { offsetX, offsetY, addMouseEvent, removeMouseEvent } = useMouse()
const { addBroadEvent, removeBroadEvent } = useBroad()
const { width, height } = useWindowSize()
const statsDetail = ref({ frameWidth: 0 })
let statsTask = null
const rtcConfiguration = {
  iceServers: [
    {
      urls: userInfo.value.ice.stun.url
    },
    {
      urls: [userInfo.value.ice.turn.url],
      credential: userInfo.value.ice.turn.pwd,
      username: userInfo.value.ice.turn.user
    }
  ]
  // iceTransportPolicy: 'relay' // 转为中继模式
}
console.log(rtcConfiguration)
/**
 * @description 初始化连接
 */
onMounted(async () => {
  statsTask && clearInterval(statsTask)
  createP2PConnection()
  document.addEventListener('pointerlockchange', lockChange, false)
  const search = getQueryParams()
  console.log(search)
})

/**
 * @description 卸载定时器和事件监听
 */
onUnmounted(() => {
  clearInterval(statsTask)
  document.removeEventListener('pointerlockchange', lockChange)
})

/**
 * @description 监听鼠标的移动设置自定义指针的位置
 */
watch([offsetX, offsetY], () => {
  if (isMouseLock.value) {
    offsetX.value = Math.max(0, Math.min(videoStream.value.offsetWidth, offsetX.value))
    offsetY.value = Math.max(0, Math.min(videoStream.value.offsetHeight, offsetY.value))
    cursorRef.value.style.transform = 'translate(' + offsetX.value + 'px,' + offsetY.value + 'px)'
  }
})

/**
 * @description 监听收到视频流的尺寸同时设置video标签的尺寸
 */
watch(
  () => statsDetail.value.frameWidth,
  (n, o) => {
    if (!o && n > 0) {
      setVideoSize()
    }
  }
)

/**
 * @description 监听屏幕尺寸变化
 */
watch([width, height], () => {
  throttleSize()
})
const throttleSize = useThrottleFn(() => {
  setVideoSize()
}, 100)

/**
 * 初始化p2p连接
 */
const p2pConnectOk = () => {
  console.log('p2p连接成功...')
  reportP2pStatus()
}
const signaling = new SignalingChannel()
const p2p = new Owt.P2P.P2PClient(
  {
    audioEncodings: true,
    videoEncodings: [
      {
        codec: {
          name: 'h264'
        }
      },
      {
        codec: {
          name: 'vp9'
        }
      },
      {
        codec: {
          name: 'vp8'
        }
      }
    ],
    rtcConfiguration
  },
  signaling,
  p2pConnectOk
)

/**
 * 添加键盘鼠标监听事件
 */
watch(
  () => isStream.value,
  (val) => {
    if (val) {
      // 添加监听事件
      console.log('添加键鼠事件...')
      addBroadEvent(p2p, remoteId)
      if (!isMouseLock.value) {
        addMouseEvent(videoStream.value, p2p, remoteId)
      }
    } else {
      // 添加监听事件
      console.log('移除键鼠事件...')
      removeMouseEvent()
      removeBroadEvent()
    }
  }
)

/**
 * 测试视频显示操作
 */
const createVideo = () => {
  isStream.value = true
  statsDetail.value = {
    frameWidth: 1920,
    frameHeight: 1080
  }
  videoStream.value.src = 'https://start.gtimg.com/act/video/pcweb_banner_1705315316.mp4'
}

/**
 * 创建p2p链接
 */
const createP2PConnection = async (tag = true) => {
  if (!tag) {
    createVideo()
    return
  }
  try {
    await p2p.connect({
      host: userInfo.value.websocketUrl,
      token: userInfo.value.localId
    })
    setRemoteIds()
    console.log('连接成功...')
  } catch (err) {
    console.log(err)
  }
}

/**
 * @description 上报p2p连接成功状态
 */
const reportP2pStatus = () => {
  const message = getParams(MsgType.REPORT_DATA, {
    report: {
      reportType: 3,
      status: 1
    }
  })
  sendMessage(message)
}

/**
 * 设置远端id
 */
const setRemoteIds = () => {
  p2p.allowedRemoteIds = [remoteId]
}

/**
 * p2p监听流
 */
p2p.addEventListener('streamadded', (e) => {
  console.log('收到流')
  // 监听流是否断开
  e.stream.addEventListener('ended', () => {
    clearInterval(statsTask)
    console.log('Stream is removed...')
  })
  // 判断是否收到流
  isStream.value = true
  console.log(e.stream)
  if (e.stream.source.audio || e.stream.source.video) {
    videoStream.value.srcObject = e.stream.mediaStream
  }
  // 监听推流信息
  statsTask = setInterval(() => {
    getStreamStat()
  }, 1000)
})

/**
 * 监听鼠标信息
 */
p2p.addEventListener('messagereceived', () => {})

/**
 * 获取推流信息
 */
const getStreamStat = async () => {
  const statsResult = await p2p.getStats(remoteId)
  statsResult.forEach((stats) => {
    if (stats.type === 'inbound-rtp' && stats.kind === 'video') {
      statsDetail.value = stats
    } else if (stats.type === 'remote-outbound-rtp') {
      console.log(stats)
    }
  })
}

/**
 * 设置菜单项的属性
 */
const changeAction = (obj) => {
  if (obj.type === 'size') {
    setVideoSize()
  }
}

/**
 * 设置视频自适应尺寸, 如果是全屏状态则不处理
 */
const setVideoSize = () => {
  if (screenType.value === 'auto') {
    if (statsDetail.value.frameWidth > statsDetail.value.frameHeight) {
      // 横屏-自适应比例
      if (statsDetail.value.frameWidth > width.value) {
        let _width = width.value
        let _height = (width.value / statsDetail.value.frameWidth) * statsDetail.value.frameHeight
        if (_height > height.value) {
          _height = height.value
          _width = (height.value / statsDetail.value.frameHeight) * statsDetail.value.frameWidth
        }
        videoBox.value.style.height = _height + 'px'
        videoBox.value.style.width = _width + 'px'
      } else {
        videoBox.value.style.width = width.value + 'px'
        videoBox.value.style.height = height.value + 'px'
      }
    } else {
      // 竖屏-自适应比例
      if (statsDetail.value.frameHeight > height.value) {
        videoBox.value.style.width =
          (height.value / statsDetail.value.frameHeight) * statsDetail.value.frameWidth + 'px'
        videoBox.value.style.height = height.value + 'px'
      } else {
        videoBox.value.style.width = width.value + 'px'
        videoBox.value.style.height = height.value + 'px'
      }
    }
  } else {
    videoBox.value.style.width = '100vw'
    videoBox.value.style.height = '100vh'
  }
}

/**
 * 监听鼠标锁定状态
 */
const lockChange = () => {
  if (
    document.pointerLockElement === videoStream.value ||
    document.mozPointerLockElement === videoStream.value ||
    document.webkitPointerLockElement === videoStream.value
  ) {
    addMouseEvent(videoStream.value, p2p, remoteId)
  } else {
    removeMouseEvent()
  }
}

/**
 * 锁定鼠标
 */
const lockMouse = () => {
  videoStream.value.requestPointerLock({
    // unadjustedMovement: true
  })
}

/**
 * 解锁鼠标
 */
const unlockMouse = () => {
  if (
    document.pointerLockElement === videoStream.value ||
    document.mozPointerLockElement === videoStream.value ||
    document.webkitPointerLockElement === videoStream.value
  ) {
    document.exitPointerLock()
  } else {
    // 切换默认解锁模式时添加鼠标事件
    addMouseEvent(videoStream.value, p2p, remoteId)
  }
}

/**
 * 点击视频画面锁定鼠标
 */
const clickLockMouse = (event) => {
  // 开启声音
  if (videoStream.value.muted) {
    videoStream.value.muted = false
  }
  // 判断鼠标是否需要锁屏以及是否处在锁屏状态
  if (isMouseLock.value && !document.pointerLockElement) {
    if (!offsetX.value)
      cursorRef.value.style.transform = 'translate(' + event.offsetX + 'px,' + event.offsetY + 'px)'
    lockMouse()
  }
}
</script>
<template>
  <div class="peer-stream">
    <LoadGame v-model="isStream"></LoadGame>
    <!--配置菜单信息-->
    <action-menu
      :stats-detail="statsDetail"
      @changeAction="changeAction"
      @lockMouse="lockMouse"
      @unlockMouse="unlockMouse"
    ></action-menu>
    <!--游戏画面渲染-->
    <div class="video-box" ref="videoBox" v-show="isStream">
      <video
        @click="clickLockMouse"
        ref="videoStream"
        class="game-video"
        id="game-video"
        muted
        autoplay
      ></video>
      <!--鼠标锁定时显示指针-->
      <div
        v-show="isMouseLock"
        ref="cursorRef"
        class="cursor-bg w-[32px] h-[32px] absolute z-10 top-0 left-0"
      ></div>
    </div>
  </div>
</template>
<style scoped lang="scss">
.peer-stream {
  width: 100vw;
  height: 100vh;
  overflow: hidden;
  background: url('@/assets/images/bg-game-1.jpg') no-repeat;
  background-size: cover;
  .video-box {
    position: fixed;
    overflow: hidden;
    z-index: 9;
    width: 0;
    height: 0;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    .cursor-bg {
      background: url('')
        0% 0% / 100% 100%;
      pointer-events: none;
    }
    .game-video {
      width: 100%;
      height: 100%;
      object-fit: fill;
    }
  }
}
</style>
